package com.zhou.project.configurations.weblogger;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zhou.project.configurations.weblogger.annotation.LoggerOperation;
import com.zhou.project.modules.system.logger.entity.Logger;
import com.zhou.project.modules.system.logger.service.LoggerService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * @author zhouhonggang
 * @version 1.0.0
 * @project spring-boot-project
 * @datetime 2021/9/26 14:15
 * @description: AOP扫描注解添加日志
 */
@Aspect
@Component
//@Lazy
public class LoggerAfterAdvice {

    @Autowired
    private LoggerService loggerService;

    /**
     * 定义切入点拦截@LoggerAnnotation注解
     * 此处的切点是注解的方式，也可用包名的方式达完成
     */
    @Pointcut("@annotation(com.zhou.project.configurations.weblogger.annotation.LoggerOperation)")
    public void logger(){}

    /**
     * 通过环绕通知完成日志记录
     * @param joinPoint 连接点
     * @return 连接点方法返回值
     */
    @Around("logger()")
    public Object around(ProceedingJoinPoint joinPoint)
    {
        //开始计时
        long start = System.currentTimeMillis();
        Object result = null;
        try {
            //执行放行动作
            result = joinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        } finally {
            //结束计时
            long end = System.currentTimeMillis();
            //耗时时间
            long executeTime = end - start;
            //获取请求对象
            RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
            ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
            HttpServletRequest request = (HttpServletRequest) servletRequestAttributes.getRequest();
            //客户端IP地址
            String requestIpaddr = request.getRemoteAddr();
            //请求方式
            String requestMethod = request.getMethod();
            //统一资源定位符
            String requestUrl = request.getRequestURL().toString();

            MethodSignature signature = (MethodSignature)joinPoint.getSignature();

            Logger entity = new Logger();
            //获取注解类
            LoggerOperation annotation = signature.getMethod().getAnnotation(LoggerOperation.class);
            if(!ObjectUtils.isEmpty(annotation))
            {
                entity.setModule(annotation.module());
                entity.setType(annotation.operationType().getValue());
                entity.setMessage(annotation.message());
                entity.setLevel(annotation.level());
            }
            entity.setRequestUrl(requestUrl);
            entity.setRequestMethod(requestMethod);
            entity.setRequestIpaddr(requestIpaddr);
            entity.setExecuteTime(executeTime);

            ObjectMapper mapper = new ObjectMapper();
            try {
                String returnValue = mapper.writeValueAsString(result);
                entity.setReturnValue(returnValue);
                String executeParams = mapper.writeValueAsString(joinPoint.getArgs());
                entity.setExecuteParams(executeParams);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }

            loggerService.save(entity);
        }
        return result;
    }

}
